<template>
  <el-button @click="start" :type="btnType" :disabled="canGetCode">
    <span>{{ text }}</span>
  </el-button>
</template>

<script>
/**
 * verificationCode 验证码输入框
 * @description 考虑到用户实际发送验证码的场景，可能是一个按钮，也可能是一段文字，提示语各有不同，所以本组件 不提供界面显示，只提供提示语
 * @property {Number String} seconds 倒计时所需的秒数（默认60）
 * @property {Boolean} disabled 开始前是否可点击（阻止不可点击）
 * @property {String} start-text 开始前的提示语（默认获取验证码）
 * @property {String} change-text 倒计时期间的提示语，必须带有字母"x"（默认X秒重新获取）
 * @property {String} end-text 倒计结束的提示语（默认重新获取）
 * @event {Function} change 倒计时期间，每秒触发一次
 * @event {Function} start 开始倒计时触发
 * @event {Function} end 结束倒计时触发
 * @example <edu-verification-code></edu-verification-code>
 */
export default {
  name: 'edu-verification-code',
  props: {
    // 按钮类型
    btnType: {
      type: String,
      default: 'primary'
    },
    // 倒计时总秒数
    seconds: {
      type: [String, Number],
      default: 60
    },
    // 禁止状态
    disabled: {
      type: Boolean,
      default: false
    },
    // 尚未开始时提示
    startText: {
      type: String,
      default: '获取验证码'
    },
    // 正在倒计时中的提示
    changeText: {
      type: String,
      default: 'X秒重新获取'
    },
    // 倒计时结束时的提示
    endText: {
      type: String,
      default: '重新获取'
    }
  },
  data() {
    return {
      secNum: this.seconds,
      timer: null,
      canGetCode: this.disabled, // 是否可以执行验证码操作
      text: this.startText
    }
  },
  watch: {
    seconds: {
      immediate: true,
      handler(n) {
        this.secNum = n
      }
    },
    disabled: {
      immediate: true,
      handler(n) {
        this.canGetCode = n
      }
    }
  },
  methods: {
    // 开始倒计时
    start() {
      // 防止快速点击获取验证码的按钮而导致内部产生多个定时器导致混乱
      if (this.timer) {
        clearInterval(this.timer)
        this.timer = null
      }
      this.$emit('start')
      this.canGetCode = true
      // 这里放这句，是为了一开始时就提示，否则要等setInterval的1秒后才会有提示
      this.changeEvent(this.changeText.replace(/x|X/, this.secNum))
      this.timer = setInterval(() => {
        if (--this.secNum) {
          // 用当前倒计时的秒数替换提示字符串中的"x"字母
          this.changeEvent(this.changeText.replace(/x|X/, this.secNum))
        } else {
          clearInterval(this.timer)
          this.timer = null
          this.changeEvent(this.endText)
          this.secNum = this.seconds
          this.$emit('end')
          this.canGetCode = false
        }
      }, 1000)
    },
    changeEvent(text) {
      this.text = text
      this.$emit('change', text)
    }
  },
  // 组件销毁的时候，清除定时器，否则定时器会继续存在，系统不会自动清除
  beforeDestroy() {
    clearTimeout(this.timer)
    this.timer = null
  }
}
</script>
